/**
 * Copyright (C) 2025 pony working team
 * SPDX-License-Identifier: MulanPSL-2.0
 */

/* includes (local) ----------------------------------------------------------*/
#include "x_hook_table.h"
#include "x_warn.h"
/* includes (standard library, system) ---------------------------------------*/
#include <stdint.h>
/* includes (other library) --------------------------------------------------*/
/* includes (project) --------------------------------------------------------*/
#include <k_task.h>

/* defines -------------------------------------------------------------------*/
/* typedefs ------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables (global) --------------------------------------------------------*/
/* variables (extern) --------------------------------------------------------*/
/* variables (local) ---------------------------------------------------------*/
/* inlines -------------------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/

/**
 * hook_table_add - add a routine to the a hook table
 * @hooks: the hook table
 * @slots: the number of slots in the table
 * @pfn:   the interrupt hook callback
 *
 * return: 0 on success, negative value on error
 */
int hook_table_add(uintptr_t *hooks, int slots, uintptr_t pfn)
{
    int i;

    task_lock();

    for (i = 0; i < slots; i++) {
        if (hooks[i] == 0) {
            hooks[i] = pfn;
            break;
        }
    }

    task_unlock();

    WARN_ON(i == slots, return -1, "Not enough hook slot, hook_table = %p, pfn = %p!", hooks, pfn);

    return 0;
}

/**
 * hook_table_del - delete a routine from the a hook table
 * @hooks: the hook table
 * @slots: the number of slots in the table
 * @pfn:   the interrupt hook callback
 *
 * return: 0 on success, negative value on error
 */
int hook_table_del(uintptr_t *hooks, int slots, uintptr_t pfn)
{
    int i;

    task_lock();

    for (i = 0; i < slots; i++) {
        if (hooks[i] == pfn) {
            hooks[i] = 0;
            break;
        }
    }

    while (i < (slots - 1)) {
        if (hooks[i + 1] == 0) {
            break;
        }

        hooks[i] = hooks[i + 1];
        hooks[i + 1] = 0;
        i++;
    }

    task_unlock();

    return 0;
}
